package com.example.demo.util;

import com.alibaba.fastjson.JSON;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;

// 标记为配置类
@Configuration
public class TokenInterceptor implements HandlerInterceptor {
    private long refreshTime = 1000 * 60 * 60 * 3; // TOKEN过期时间为3小时
    // 重写preHandle方法
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //获取session中的token
        HttpSession session = request.getSession();
        String token = (String) session.getAttribute("token");
        if (null == token || "".equals(token.trim()))  {
            returnJson(response, JSONCreate("未查询到TOKEN"));
            return false;
        }
        // 调用TokenUtil工具类解析token
        Map<String, String> map = TokenUtil.parseToken(token);
        String userId = map.get("userId");
        String userRole = map.get("userRole");
        long times = System.currentTimeMillis() - Long.parseLong(map.get("time"));
        //1.判断 token 是否过期
        if (times < refreshTime) {
            //2.判断用户是否登录
            if (null == userId || "".equals(userId) || !session.getAttribute("userId").equals(userId) ) {
                returnJson(response, JSONCreate("登录信息错误"));
                return false;
            }
            //3.判断用户角色
            if (null == userRole || "".equals(userRole) || !session.getAttribute("userRole") .equals(userRole)) {
                returnJson(response, JSONCreate("角色信息错误"));
                return false;
            }
            return true;
        }else {
            returnJson(response, JSONCreate("TOKEN过期"));
            return false;
        }
    }

    // 重写postHandle方法
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response,
                           Object handler, ModelAndView modelAndView) {
        // 获取与当前HTTP请求关联的会话对象，如果不存在则创建一个新的会话
        HttpSession session = request.getSession();
        String token = (String) session.getAttribute("token");
        // 获取当前时间的毫秒数，用作生成token的时间戳
        long time = System.currentTimeMillis();
        Map<String, String> map = TokenUtil.parseToken(token);
        String userId = map.get("userId");
        String userRole = map.get("userRole");
        // 使用TokenUtil工具类根据用户ID、角色名和时间戳生成一个token
        token = TokenUtil.getToken(userId, userRole, time);
        // 修改Session中的TOKEN为最新的
        session.setAttribute("token", token);
        // 将生成token的时间戳存储在会话中，键为"time"
        session.setAttribute("time", time);
    }

    // 重写afterCompletion方法
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        // 请求执行后
        System.out.println("请求结束了");
    }

    // 定义一个私有方法，用于向客户端返回JSON格式的数据
    private void returnJson(HttpServletResponse response, String result) throws Exception {
        // 声明一个PrintWriter对象，用于向HTTP响应输出流写入数据
        PrintWriter writer = null;
        // 设置响应的字符编码为UTF-8，确保中文等非ASCII字符能够正确显示
        response.setCharacterEncoding("UTF-8");
        // 设置响应的内容类型为HTML，并指定字符集为UTF-8
        response.setContentType("text/html; charset=utf-8");
        try {
            // 获取响应的输出流，并赋值给PrintWriter对象
            writer = response.getWriter();
            // 将结果字符串写入到响应的输出流中
            writer.print(result);
        } catch (IOException e) {
            // 如果在写入过程中发生IO异常，则捕获该异常（这里可以根据实际情况添加日志记录或其他处理）
        } finally {
            // 无论是否发生异常，都尝试关闭PrintWriter对象，释放资源
            if (writer != null) {
                writer.close();
            }
        }
    }

    private String JSONCreate(String message){
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("{\"code\":-1,\"message\":\"");
        stringBuffer.append(message);
        stringBuffer.append("\"}");
        return stringBuffer.toString();
    }
}
